package com.ly.heart.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ly.common.PageParam;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.core.domain.entity.SysUser;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.*;
import com.ly.heart.domain.dto.KingFinanceReceiptDto;
import com.ly.heart.domain.dto.StartProcessDto;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.heart.domain.vo.KingFinanceReceiptMenuVo;
import com.ly.heart.domain.vo.KingFinanceReceiptVo;
import com.ly.heart.mapper.KingFinanceReceiptMapper;
import com.ly.heart.service.*;
import com.ly.heart.service.king.ReceiptPushService;
import com.ly.heart.util.ChineseToPinyin;
import com.ly.system.service.ISysDeptService;
import com.ly.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;

/**
 * 财务模块-收款单,推金蝶Service业务层处理
 * @author wutao
 * @date 2024-06-19
 */
@Service
@Slf4j
public class KingFinanceReceiptServiceImpl extends ServiceImpl<KingFinanceReceiptMapper, KingFinanceReceiptEntity> implements IKingFinanceReceiptService {

    @Resource
    private KingFinanceReceiptMapper kingFinanceReceiptEntityMapper;
    @Resource
    private ISaleOrderService iSaleOrderService;
    @Resource
    private ISaleCollectionPlanService iSaleCollectionPlanService;
    @Resource
    private IKingInvoicePayableReceivableOtherDetailService iKingInvoicePayableReceivableOtherDetailService;
    @Resource
    private IActModelService iActModelService;
    @Resource
    private IKingInvoiceReceivableService iKingInvoiceReceivableService;
    @Resource
    private IKingFinanceReceiptDetailService iKingFinanceReceiptDetailService;
    @Resource
    private IKingFinanceReceiptRefundDetailService iKingFinanceReceiptRefundDetailService;
    @Resource
    private ICustomerService iCustomerService;
    @Resource
    private ISupplierService iSupplierService;
    @Resource
    private ISysDeptService iSysDeptService;
    @Resource
    private ISysUserService iSysUserService;
    @Resource
    private IKingBaseTransactionsCompanyService iKingBaseTransactionsCompanyService;
    @Resource
    private IKingBaseBankService iKingBaseBankService;
    @Resource
    private IActTaskCommentService iActTaskCommentService;
    @Resource
    private IKingBaseCurrencyService iKingBaseCurrencyService;
    @Resource
    private IKingPayableReceivableVerificationService iKingPayableReceivableVerificationService;
    @Resource
    private ReceiptPushService receiptPushService;

    /**
     * 查询财务模块-收款单,推金蝶
     * @param id 财务模块-收款单,推金蝶ID
     * @return 财务模块-收款单,推金蝶
     */
    @Override
    public KingFinanceReceiptVo selectKingFinanceReceiptEntityById (String id) {
        KingFinanceReceiptVo vo = new KingFinanceReceiptVo ();
        KingFinanceReceiptEntity kingFinanceReceiptEntity = kingFinanceReceiptEntityMapper.selectKingFinanceReceiptEntityById ( id );
        //获取往来单位
        String transactionCompanyName = getCompanyName ( kingFinanceReceiptEntity.getTransactionCompanyType (), kingFinanceReceiptEntity.getTransactionCompanyId () );
        kingFinanceReceiptEntity.setTransactionCompanyName ( transactionCompanyName );
        //获取付款单位
        String payCompanyName = getCompanyName ( kingFinanceReceiptEntity.getPayDeptType (), kingFinanceReceiptEntity.getPayDeptId () );
        kingFinanceReceiptEntity.setPayDeptName ( payCompanyName );
        //明细
        KingFinanceReceiptDetailEntity receiptDetailEntity = new KingFinanceReceiptDetailEntity ();
        receiptDetailEntity.setRelationId ( id );
        List<KingFinanceReceiptDetailEntity> list = iKingFinanceReceiptDetailService.queryList ( receiptDetailEntity );
        vo.setKingFinanceReceiptEntity ( kingFinanceReceiptEntity ).setKingFinanceReceiptDetailEntities ( list );
        return vo;
    }

    /**
     * 查询财务模块-收款单,推金蝶列表
     * @param kingFinanceReceiptEntity 财务模块-收款单,推金蝶
     * @return 财务模块-收款单,推金蝶
     */
    @Override
    public List<KingFinanceReceiptEntity> selectKingFinanceReceiptEntityList (KingFinanceReceiptEntity kingFinanceReceiptEntity) {
        kingFinanceReceiptEntity.setIsUsed ( ConstUtil.IS_USED_YES );
        kingFinanceReceiptEntity.setPage ( ( kingFinanceReceiptEntity.getPage () - 1 ) * kingFinanceReceiptEntity.getLimit () );
        List<KingFinanceReceiptEntity> kingFinanceReceiptEntities = kingFinanceReceiptEntityMapper.selectKingFinanceReceiptEntityList ( kingFinanceReceiptEntity );
        // 提取Id
        List<String> ids = kingFinanceReceiptEntities.stream ().map ( KingFinanceReceiptEntity :: getId ).collect ( Collectors.toList () );
        if ( ! CollectionUtils.isEmpty ( ids ) ) {
            kingFinanceReceiptEntities.forEach ( receipt -> {
                List<KingFinanceReceiptRefundDetailEntity> kingFinanceReceiptRefundDetailEntities = iKingFinanceReceiptRefundDetailService.queryList ( receipt.getId () );
                double sum = kingFinanceReceiptRefundDetailEntities.stream ().mapToDouble ( detail -> Double.parseDouble ( detail.getActualRefundMoney () ) ).sum ();
                receipt.setRefundAmount ( String.valueOf ( sum ) );
                //获取往来单位
                String transactionCompanyName = getCompanyName ( receipt.getTransactionCompanyType (), receipt.getTransactionCompanyId () );
                receipt.setTransactionCompanyName ( transactionCompanyName );
                //获取付款单位
                String payCompanyName = getCompanyName ( receipt.getPayDeptType (), receipt.getPayDeptId () );
                receipt.setPayDeptName ( payCompanyName );
                //处理最后一个审批人
                ActTaskCommentEntity actTaskCommentEntity = iActTaskCommentService.queryLastComment ( receipt.getInstanceId () );
                if ( actTaskCommentEntity != null ) {
                    receipt.setApprovedUser ( actTaskCommentEntity.getApprovedUser () );
                    receipt.setApprovedRemark ( actTaskCommentEntity.getRemark () );
                }
                //任务信息
                ActCurrentTaskVo currentTaskVo = iActModelService.getCurrentTaskByInstanceId ( receipt.getInstanceId () );
                Optional.ofNullable ( currentTaskVo ).ifPresent ( currentTask -> {
                    receipt.setCurrentTask ( currentTask );
                } );
            } );
        }
        return kingFinanceReceiptEntities;
    }

    @Override
    public Integer selectKingFinanceReceiptEntityCount (KingFinanceReceiptEntity kingFinanceReceiptEntity) {
        Integer count = kingFinanceReceiptEntityMapper.selectKingFinanceReceiptEntityCount ( kingFinanceReceiptEntity );
        return count;
    }

    /**
     * 新增财务模块-收款单,推金蝶
     * 1、普通新增
     * 2、应收单下推收款单
     * 3、其他应收单下推收款单
     * 4、应付票据自动生成收款单
     * 5、工程下推
     * @param kingFinanceReceiptDto 财务模块-收款单,推金蝶
     * @return 结果
     */
    @Override
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult draft (KingFinanceReceiptDto kingFinanceReceiptDto) {
        //1.处理收款单基本信息
        KingFinanceReceiptEntity receiptEntity = kingFinanceReceiptDto.getKingFinanceReceiptEntity ();
        receiptEntity.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
        //receiptEntity.setDeptId ( CurrentUserUtil.getCompanyId () );
        receiptEntity.setCreateBy ( StringUtils.isNoneBlank ( receiptEntity.getCreateBy () ) ? receiptEntity.getCreateBy () : SecurityUtils.getLoginUser ().getUser ().getUserId () );
        receiptEntity.setCreateTime ( DateUtils.getNowDate () );
        String py = ChineseToPinyin.getFirstLetter ( "收款单" );
        int count = this.count ();
        String countStr = String.format ( "%08d", count );
        receiptEntity.setDocNo ( py.concat ( countStr ) );
        //检查应收单
        if ( receiptEntity.getSourceDocType () == KingConstUtil.RECEIPT_TYPE_RECEIVABLE ) {
            checkReceivable ( kingFinanceReceiptDto.getKingFinanceReceiptDetailEntities (), receiptEntity );
        }
        //2.处理关联销售订单的收款计划
        updateOrderCollectionPlan ( kingFinanceReceiptDto.getKingFinanceReceiptDetailEntities (), receiptEntity );
        //3.处理金蝶上收款单明细列表信息
        int insertReceiptDetail = updateReceiptDetail ( kingFinanceReceiptDto.getKingFinanceReceiptDetailEntities (), receiptEntity.getId () );
        if ( insertReceiptDetail == 0 ) {
            return AjaxResult.error ( "新增收款单的收款明细失败" );
        }
        receiptEntity.setState ( ConstUtil.STATE_IN_DRAFT );
        boolean save = this.save ( receiptEntity );
        if ( ! save ) {
            return AjaxResult.error ( "暂存收款单失败" );
        }
        return AjaxResult.success ( "暂存收款单成功", receiptEntity.getId () );
    }

    /**
     * 提交收款单
     * @param receiptEntity
     * @return
     */
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult submit (KingFinanceReceiptEntity receiptEntity) {
        //1.处理收款单基本信息
        if ( StringUtils.isBlank ( receiptEntity.getId () ) ) {
            return AjaxResult.error ( "请先暂存该单据！" );
        }
        //处理审批流
        StartProcessDto startDto = new StartProcessDto ().
                setBusinessId ( receiptEntity.getId () ).
                setBusinessType ( receiptEntity.getBusinessType () ).setModelId ( receiptEntity.getModelId () ).
                setBusinessName ( "收款单_".concat ( receiptEntity.getId () ) );
        String instanceId = iActModelService.startProcess ( startDto );
        boolean save = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptEntity> ().
                set ( KingFinanceReceiptEntity :: getInstanceId, instanceId ).
                set ( KingFinanceReceiptEntity :: getState, ConstUtil.STATE_IN_PROCESS ).
                eq ( KingFinanceReceiptEntity :: getId, receiptEntity.getId () ) );
        if ( ! save ) {
            return AjaxResult.error ( "提交收款单失败" );
        }
        return AjaxResult.success ();
    }

    @Override
    public KingFinanceReceiptEntity querySingleById (String id) {
        KingFinanceReceiptEntity receiptEntity = kingFinanceReceiptEntityMapper.querySingleById ( id );
        return receiptEntity;
    }

    /**
     * 付款单审批成功后，进行业务处理回调
     * 1、处理对应销售订单的付款金额
     * 2、处理与应收单的核销
     * 3、修改审批状态
     * 4、推送金蝶
     * @param id
     * @return
     */
    @Override
    public AjaxResult approve ( String id ) {
        log.info ( "收款单审批后业务处理回调..." );
        KingFinanceReceiptEntity receiptEntity = querySingleById ( id );
        if ( receiptEntity == null ) {
            throw new CustomException ( "该收款单不存在！" );
        }
        //1.处理销售订单的收款信息
        updateSaleOrderReceipt ( receiptEntity );
        log.info ( "收款单更新对应销售订单付款金额成功。" );
        //2.处理和应收单的核销
        updateVerification ( receiptEntity );
        log.info ( "收款单更新对应应收单核销记录成功。" );
        //3.修改审批状态
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptEntity> ().
                set ( KingFinanceReceiptEntity :: getState, ConstUtil.STATE_FINISH ).
                eq ( KingFinanceReceiptEntity :: getId, id ) );
        if ( ! update ) {
            throw new CustomException ( "修改收款单审批状态失败！" );
        }
        log.info ( "收款单更新审批流状态成功" );
        //receiptPushService.push ( receiptEntity );
        return AjaxResult.success ( "收款单审核完成并成功推送金蝶。" );
    }

    /**
     * 修改财务模块-收款单,推金蝶
     * @param kingFinanceReceiptDto 财务模块-收款单,推金蝶
     * @return 结果
     */
    @Override
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult updateKingFinanceReceiptEntity (KingFinanceReceiptDto kingFinanceReceiptDto) {
        KingFinanceReceiptEntity receiptEntity = kingFinanceReceiptDto.getKingFinanceReceiptEntity ();
        receiptEntity.setUpdateTime ( DateUtils.getNowDate () );
        receiptEntity.setUpdateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
        boolean b = this.updateById ( receiptEntity );
        if ( ! b ) {
            throw new CustomException ( "修改收款单基本信息失败！" );
        }
        //检查应收单
        if ( receiptEntity.getSourceDocType () == KingConstUtil.RECEIPT_TYPE_RECEIVABLE ) {
            checkReceivable ( kingFinanceReceiptDto.getKingFinanceReceiptDetailEntities (), receiptEntity );
        }
        //2.处理关联销售订单的收款计划
        updateOrderCollectionPlan ( kingFinanceReceiptDto.getKingFinanceReceiptDetailEntities (), receiptEntity );
        //3.处理金蝶上收款单明细列表信息
        int insertReceiptDetail = updateReceiptDetail ( kingFinanceReceiptDto.getKingFinanceReceiptDetailEntities (), receiptEntity.getId () );
        if ( insertReceiptDetail == 0 ) {
            return AjaxResult.error ( "新增收款单的收款明细失败" );
        }
        return AjaxResult.success ();
    }

    /**
     * 批量删除财务模块-收款单,推金蝶
     * @param ids 需要删除的财务模块-收款单,推金蝶ID
     * @return 结果
     */
    @Override
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult deleteKingFinanceReceiptEntityByIds (String[] ids) {
        LambdaUpdateWrapper<KingFinanceReceiptEntity> receiptUpdate = new LambdaUpdateWrapper<> ();
        receiptUpdate.set ( KingFinanceReceiptEntity :: getIsUsed, ConstUtil.IS_USED_NO ).in ( KingFinanceReceiptEntity :: getId, ids );
        boolean update = this.update ( receiptUpdate );
        if ( ! update ) {
            throw new CustomException ( "删除收款单失败！" );
        }
        LambdaUpdateWrapper<KingFinanceReceiptDetailEntity> detailUpdate = new LambdaUpdateWrapper<> ();
        detailUpdate.set ( KingFinanceReceiptDetailEntity :: getIsUsed, ConstUtil.IS_USED_NO ).in ( KingFinanceReceiptDetailEntity :: getRelationId, ids );
        iKingFinanceReceiptDetailService.update ( detailUpdate );
        return AjaxResult.success ( "删除收款单成功" );
    }

    /**
     * 收款退款单选择收款单
     * @param kingFinanceReceiptEntity
     * @return
     */
    @Override
    public AjaxResult queryList ( KingFinanceReceiptEntity kingFinanceReceiptEntity ) {
        kingFinanceReceiptEntity.setPage ( ( kingFinanceReceiptEntity.getPage () - 1 ) * kingFinanceReceiptEntity.getLimit () );
        kingFinanceReceiptEntity.setIsUsed ( ConstUtil.IS_USED_YES );
        List<KingFinanceReceiptMenuVo> kingFinanceReceiptMenuVos = kingFinanceReceiptEntityMapper.queryList ( kingFinanceReceiptEntity );
        kingFinanceReceiptMenuVos.forEach ( receipt -> {
            String transactionCompanyName = getCompanyName ( receipt.getTransactionCompanyType (), receipt.getTransactionCompanyId () );
            receipt.setTransactionCompanyName ( transactionCompanyName );
            //获取付款单位
            String payCompanyName = getCompanyName ( receipt.getPayDeptType (), receipt.getPayDeptId () );
            receipt.setPayCompanyName ( payCompanyName );
        } );
        Integer integer = kingFinanceReceiptEntityMapper.queryCount ( kingFinanceReceiptEntity );
        PageParam p = new PageParam ();
        p.setRecords ( kingFinanceReceiptMenuVos ).setTotal ( integer );
        return AjaxResult.success ( p );
    }

    /**
     * 应收单下推收款单
     * @param receiptEntity：收款对象
     */
    private void checkReceivable (List<KingFinanceReceiptDetailEntity> kingFinanceReceiptDetailEntities, KingFinanceReceiptEntity receiptEntity) {
        //立账类型为业务应收
        kingFinanceReceiptDetailEntities = kingFinanceReceiptDetailEntities.stream ().filter ( detail -> StringUtils.isNotBlank ( detail.getSourceId () ) ).collect ( Collectors.toList () );
        List<String> ids = kingFinanceReceiptDetailEntities.stream ().map ( KingFinanceReceiptDetailEntity :: getSourceId ).collect ( Collectors.toList () );
        List<KingInvoiceReceivableEntity> list = iKingInvoiceReceivableService.list ( new LambdaQueryWrapper<KingInvoiceReceivableEntity> ().in ( KingInvoiceReceivableEntity :: getId, ids ) );
        boolean is = list.stream ().map ( KingInvoiceReceivableEntity :: getAccountType ).allMatch ( p -> p == 1 );
        if ( ! is ) {
            throw new CustomException ( "所选应收单的立账类型必须是业务应收！" );
        }
        //选择的多个应收单必须是同一个客户
        boolean b = list.stream ().map ( KingInvoiceReceivableEntity :: getCustomerId ).allMatch ( p -> p.equals ( list.get ( 0 ).getCustomerId () ) );
        if ( ! b ) {
            throw new CustomException ( "分录行的应收单必须是同一个客户！" );
        }
        //分录行的应收单必须和表头的付款单位(客户)一致
        if ( list.get ( 0 ).getCustomerId ().equals ( receiptEntity.getPayDeptId () ) ) {
            throw new CustomException ( "所选单据的客户与付款单位不一致！" );
        }
        //收款单明细行《实收金额》不能大于源单（应收单）未结算金额=应收单的价税合计-已结算金额（应收单已下推收款单的实际金额）
        kingFinanceReceiptDetailEntities.forEach ( detail -> {
            //1.收款单明细行《实收金额》
            double cope = Double.parseDouble ( detail.getActualMoney () );
            //2.应收单的价税合计
            double totalTaxPrice = 0;
            Optional<KingInvoiceReceivableEntity> first = list.stream ().filter ( receivable -> receivable.getId ().equals ( detail.getSourceId () ) ).findFirst ();
            if ( first.isPresent () ) {
                KingInvoiceReceivableEntity receivableEntity = first.get ();
                totalTaxPrice = Double.parseDouble ( receivableEntity.getTotalTaxAmount () );
            }
            //3.已结算金额（应收单已下推收款单的实际金额）
            double payMoney = 0;
            KingFinanceReceiptDetailEntity one = iKingFinanceReceiptDetailService.getOne ( new QueryWrapper<KingFinanceReceiptDetailEntity> ().
                    select ( "SUM(actual_money) AS actualMoney" ).
                    eq ( "source_id", detail.getSourceId () ) );
            if ( one != null ) {
                payMoney = Double.parseDouble ( one.getActualMoney () );
            }
            if ( cope > ( totalTaxPrice - payMoney ) ) {
                throw new CustomException ( "第【" + detail.getLineNumber () + "】分录行下推实收金额超限！" );
            }
        } );
    }

    /**
     * 其他应收单下推收款单
     * @param receivableOtherEntities：所选其他应收单明细
     * @param payReceiptDetailEntities：新增收款单明细
     */
    private void checkReceivableOther (List<KingInvoiceReceivableOtherEntity> receivableOtherEntities, List<KingFinancePayDetailEntity> payReceiptDetailEntities) {
        //拿到其他应收单的明细，看每个其他应收单的总金额是多少
        List<String> ids = receivableOtherEntities.stream ().map ( KingInvoiceReceivableOtherEntity :: getId ).collect ( Collectors.toList () );
        //通过所选其他应收单id查询明细
        List<KingInvoicePayableReceivableOtherDetailEntity> list = iKingInvoicePayableReceivableOtherDetailService.list ( new QueryWrapper<KingInvoicePayableReceivableOtherDetailEntity> ().in ( "relation_other_id", ids ) );
        for ( int i = 0; i < list.size (); i++ ) {
            KingInvoicePayableReceivableOtherDetailEntity receivableOtherDetailEntity = list.get ( i );
            for ( int j = 0; j < payReceiptDetailEntities.size (); j++ ) {
                //收款单明细
                KingFinancePayDetailEntity receiptDetailEntity = payReceiptDetailEntities.get ( j );
                //其他应收单下推收款单，根据费用项目编码判断
                if ( receivableOtherDetailEntity.getFeeCode ().equals ( receiptDetailEntity.getFeeCode () ) ) {
                    //判断价格，付款单新增界面的应收金额大于其他应收单的总金额，不给通过
                    if ( Double.parseDouble ( receiptDetailEntity.getActualMoney () ) > Double.parseDouble ( receivableOtherDetailEntity.getTotalAmount () ) ) {
                        throw new CustomException ( "分录行的实收金额超限！" );
                    }
                }
            }
        }
    }

    /**
     * 新增收款退款单，校验规则
     * 校验退款单明细的实退金额以及明细行金额
     * @param receiptDetailEntities
     */
//    private void checkReceiptToRefund (List<KingFinancePayDetailEntity> receiptDetailEntities) {
//        if ( ! CollectionUtils.isEmpty ( receiptDetailEntities ) ) {
//            //源收款单明细行实退金额总和
//            double sourceActualMoney = 0;
//            for ( int i = 0; i < receiptDetailEntities.size (); i++ ) {
//                //收款退款单明细行
//                KingFinancePayDetailEntity payReceiptDetailEntity = receiptDetailEntities.get ( i );
//                String actualMoney = payReceiptDetailEntity.getActualMoney ();//明细行的实退金额
//                String sourceId = payReceiptDetailEntity.getSourceId ();//明细行的源单Id(付款单明细行Id)
//                //源单（付款单）明细行
//                KingFinanceReceiptDetailEntity receiptDetailEntity = iKingFinanceReceiptDetailService.getById ( sourceId );
//                // 所有明细行的实退金额总和
//                sourceActualMoney = CommonUtil.sum ( sourceActualMoney, Double.parseDouble ( receiptDetailEntity.getActualMoney () ) );
//                // 退款明细行的每行实退金额 不能大于 源单（付款单）明细行的金额减去已核销金额
//                if ( Double.parseDouble ( actualMoney ) > ( Double.parseDouble ( receiptDetailEntity.getActualMoney () ) - Double.parseDouble ( receiptDetailEntity.getVerifiedAmount () ) ) ) {
//                    throw new CustomException ( "明细行的退款金额超过源单明细可退款金额" );
//                }
//            }
//            //退款单明细行实退金额总和
//            double sum = receiptDetailEntities.stream ().mapToDouble ( amount -> Double.parseDouble ( amount.getActualMoney () ) ).sum ();
//            if ( sum > sourceActualMoney ) {
//                throw new CustomException ( "实退金额总和不能超过源付款单可退金额！" );
//            }
//        }
//    }


    /**
     * 更新销售订单的收款计划
     * @param receiptDetailEntities
     * @param receiptEntity
     */
    private void updateOrderCollectionPlan (List<KingFinanceReceiptDetailEntity> receiptDetailEntities, KingFinanceReceiptEntity receiptEntity) {
        //筛选：预付款+销售订单的明细
        List<KingFinanceReceiptDetailEntity> saleIds = receiptDetailEntities.stream ().filter ( d -> StringUtils.isNotBlank ( d.getSaleOrderId () ) ).collect ( Collectors.toList () );
        log.info ( "选择了销售订单-> {}", saleIds );
        if ( CollectionUtils.isEmpty ( saleIds ) ) {
            return;
        }
        //检查所有行的销售订单Id是否一致
        boolean b = saleIds.stream ().map ( KingFinanceReceiptDetailEntity :: getSaleOrderId ).allMatch ( prop -> prop.equals ( saleIds.get ( 0 ).getSaleOrderId () ) );
        if ( ! b ) {
            throw new CustomException ( "分录行的销售订单必须是同一个客户！" );
        }
        SaleOrderEntity saleOrderEntity = iSaleOrderService.getById ( saleIds.get ( 0 ).getSaleOrderId () );
        if ( ! saleOrderEntity.getCustomerId ().equals ( receiptEntity.getPayDeptId () ) ) {
            throw new CustomException ( "分录行的销售订单必须和表头填写的客户一致！" );
        }
        //保存采购订单的付款计划
        if ( ! CollectionUtils.isEmpty ( saleIds ) ) {
            iSaleCollectionPlanService.remove ( new LambdaUpdateWrapper<SaleCollectionPlanEntity> ().eq ( SaleCollectionPlanEntity :: getAssociationOrderNum, receiptEntity.getDocNo () ) );
            receiptDetailEntities.forEach ( detail -> {
                /**
                 * 校验订单预付金额：
                 * 1、预付比例=预付金额/订单价税合计总金额
                 * 2、预付金额 不能大于 该笔订单未付款金额=订单价税合计-实际预付金额
                 */
                String totalUnpaidAmount = StringUtils.isBlank ( saleOrderEntity.getUnpaidAmount () ) ? "0" : saleOrderEntity.getUnpaidAmount ();//销售订单累计未收款金额
                String totalPriceTax = StringUtils.isBlank ( saleOrderEntity.getTotalTaxPrice () ) ? "0" : saleOrderEntity.getTotalTaxPrice ();//销售订单价税合计金额
                if ( StringUtils.isBlank ( detail.getCopeMoney () ) ) {
                    throw new CustomException ( "【" + detail.getSaleOrderCode () + "】的应收金额不能为空！" );
                }
                if ( Double.parseDouble ( detail.getCopeMoney () ) > Double.parseDouble ( totalUnpaidAmount ) ) {
                    throw new CustomException ( "【" + detail.getSaleOrderCode () + "】的应收金额不能超过未收款金额【" + totalUnpaidAmount + "】元！" );
                }
                SaleCollectionPlanEntity saleCollectionPlanEntity = new SaleCollectionPlanEntity ();
                saleCollectionPlanEntity.setOrderId ( detail.getSaleOrderId () ).
                        setIsPreReceipt ( "1" ).
                        setReceivableAmount ( detail.getCopeMoney () ).
                        setReceivableRatio ( CommonUtil.divisionStr ( detail.getCopeMoney (), totalPriceTax, 5 ) ).
                        setAssociationOrderNum ( receiptEntity.getDocNo () ).
                        setNetReceiptsAmount ( detail.getActualMoney () );
                int i = iSaleCollectionPlanService.insertSaleCollectionPlan ( saleCollectionPlanEntity );
                if ( i == 0 ) {
                    throw new CustomException ( "绑定预收款单与销售订单的收款计划失败！" );
                }
            } );
        }
    }

    /**
     * 更新收款单的明细列表数据
     * @param receiptDetailEntities
     * @param receiptId
     * @return
     */
    private int updateReceiptDetail (List<KingFinanceReceiptDetailEntity> receiptDetailEntities, String receiptId) {
        if ( ! CollectionUtils.isEmpty ( receiptDetailEntities ) ) {
            iKingFinanceReceiptDetailService.remove ( new LambdaUpdateWrapper<KingFinanceReceiptDetailEntity> ().eq ( KingFinanceReceiptDetailEntity :: getRelationId, receiptId ) );
            receiptDetailEntities.forEach ( kingFinanceReceiptDetailEntity -> {
                kingFinanceReceiptDetailEntity.setRelationId ( receiptId );
                kingFinanceReceiptDetailEntity.setCreateTime ( DateUtils.getNowDate () );
                iKingFinanceReceiptDetailService.saveSingle ( kingFinanceReceiptDetailEntity );
            } );
        }
        return 1;
    }

    /**
     * 收款单审核后更新对应销售订单的收款金额
     * @param kingFinanceReceiptEntity
     */
    private void updateSaleOrderReceipt ( KingFinanceReceiptEntity kingFinanceReceiptEntity ) {
        List<KingFinanceReceiptDetailEntity> list = iKingFinanceReceiptDetailService.list ( new LambdaQueryWrapper<KingFinanceReceiptDetailEntity> ().
                eq ( KingFinanceReceiptDetailEntity :: getRelationId, kingFinanceReceiptEntity.getId () ) );
        list.forEach ( detail -> {
            String saleOrderId = detail.getSaleOrderId ();
            if ( StringUtils.isNotBlank ( saleOrderId ) ) {
                //将该订单的未收款金额和已收款金额重新计算
                SaleOrderEntity saleOrderEntity = iSaleOrderService.getById ( saleOrderId );
                String unpaidAmount = saleOrderEntity.getUnpaidAmount (); //未收款金额
                String totalCollectionAmount = saleOrderEntity.getTotalCollectionAmount ();//累计收款金额
                String receiptAmount = kingFinanceReceiptEntity.getActualMoney ();
                iSaleOrderService.update ( new LambdaUpdateWrapper<SaleOrderEntity> ().
                        set ( SaleOrderEntity :: getUnpaidAmount, CommonUtil.subStr ( unpaidAmount, receiptAmount, 2 ) ).
                        set ( SaleOrderEntity :: getTotalCollectionAmount, CommonUtil.sumStr ( totalCollectionAmount, receiptAmount, 2 ) ).
                        eq ( SaleOrderEntity :: getId, saleOrderId ) );
            }
        } );
    }


    /**
     * 更新收款单与应收单的核销记录
     * 1、自动核销：当收款单的源单是应收单时，自动核销
     * 2、匹配核销：当收款单明细行是预收款且有销售订单时，匹配核销
     * 3、手动核销：其他之外需手动核销
     *
     * @param receiptEntity
     */
    private void updateVerification ( KingFinanceReceiptEntity receiptEntity ) {
        List<KingFinanceReceiptDetailEntity> list = iKingFinanceReceiptDetailService.list ( new LambdaQueryWrapper<KingFinanceReceiptDetailEntity> ().
                eq ( KingFinanceReceiptDetailEntity :: getRelationId, receiptEntity.getId () ) );
        for ( KingFinanceReceiptDetailEntity receiptDetailEntity : list ) {
            KingInvoiceReceivableEntity receivableEntity = iKingInvoiceReceivableService.querySingleById ( receiptDetailEntity.getSourceId () );
            if ( receiptDetailEntity.getSourceDocType () == KingConstUtil.RECEIPT_TYPE_RECEIVABLE ) {
                //应收单和收款单自动核销
                if ( ! ObjectUtils.isEmpty ( receiptDetailEntity ) ) {
                    if ( receiptEntity.getPayDeptType ().equals ( "BD_Customer" ) &&
                            receivableEntity.getCustomerId ().equals ( receiptEntity.getPayDeptId () ) &&
                            receivableEntity.getCurrencyCode ().equals ( receiptEntity.getKingBaseCurrencyCode () ) &&
                            receivableEntity.getSettlementDeptId ().equals ( receiptEntity.getSettlementDeptId () )
                    ) {
                        KingPayableReceivableVerificationEntity receiptVerify = new KingPayableReceivableVerificationEntity ();
                        SysDept sysDept = iSysDeptService.getById ( receiptEntity.getSettlementDeptId () );
                        KingBaseCurrencyEntity one = iKingBaseCurrencyService.getOne ( new LambdaQueryWrapper<KingBaseCurrencyEntity> ().eq ( KingBaseCurrencyEntity :: getCode, sysDept.getStandardCurrencyCode () ) );
                        receiptVerify.setSettlementCompany ( sysDept.getDeptName () );
                        receiptVerify.setOwnCurrencyTitle ( one.getCurrencyName () );
                        receiptVerify.setPayReceiptCompany ( sysDept.getDeptName () );
                        receiptVerify.setVerificationType ( 1 );
                        receiptVerify.setType ( 2 );
                        //核销列表对象
                        String amount = Double.parseDouble ( receiptEntity.getActualMoney () ) > Double.parseDouble ( receivableEntity.getTotalTaxAmount () ) ? receivableEntity.getTotalTaxAmount () : receiptEntity.getActualMoney ();
                        KingPayableReceivableVerificationDetailEntity verifyByReceipt = new KingPayableReceivableVerificationDetailEntity ();
                        verifyByReceipt.setDoc ( "收款单" ).setDocType ( receiptEntity.getDocTypeCode () ).setDocNo ( receiptEntity.getDocNo () ).setLineNumber ( receiptDetailEntity.getLineNumber () ).
                                setBizTime ( receiptEntity.getBusinessTime () ).setTransactionDeptTitle ( receiptEntity.getTransactionCompanyName () ).setCurrencyTitle ( receiptEntity.getSettlementCurrencyName () ).
                                setRate ( receiptEntity.getRate () ).setVerificationAmount ( amount ).setPayPurpose ( receiptDetailEntity.getReceiptPurposeCode () ).setMaterialName ( receiptDetailEntity.getMaterialCode () ).setFeeItem ( receiptDetailEntity.getFeeCode () );
                        KingPayableReceivableVerificationDetailEntity verifyByReceivable = new KingPayableReceivableVerificationDetailEntity ();
                        verifyByReceivable.setDoc ( "应收单" ).setDocType ( receivableEntity.getDocTypeCode () ).setDocNo ( receivableEntity.getDocNo () ).setLineNumber ( "1" ).setBizTime ( receivableEntity.getBizTime () ).
                                setTransactionDeptTitle ( receivableEntity.getCustomerName () ).setCurrencyTitle ( receivableEntity.getCurrencyName () ).setRate ( receivableEntity.getRate () ).setVerificationAmount ( amount );
                        List<KingPayableReceivableVerificationDetailEntity> verificationDetailEntities = new ArrayList<> ();
                        verificationDetailEntities.add ( verifyByReceipt );
                        verificationDetailEntities.add ( verifyByReceivable );
                        iKingPayableReceivableVerificationService.saveSingle ( receiptVerify, verificationDetailEntities );
                    }
                }
            } else if ( StringUtils.isNotBlank ( receiptDetailEntity.getSaleOrderId () ) ) {
                // 收款单审核后可以进行匹配核销
                List<String> orderIds = list.stream ().map ( KingFinanceReceiptDetailEntity :: getSaleOrderId ).distinct ().collect ( Collectors.toList () );
                iKingPayableReceivableVerificationService.matchVerify ( 2, 4, receiptEntity.getId (), orderIds );
            }
        }
    }


    /**
     * 根据往来单位类型，获取往来单位和付款单位
     * @param companyType：单位类型，根据往来单位或付款单位的类型魔法值
     * @param companyId：单位Id，根据单位类型，选择的具体单位Id
     * @return
     */
    private String getCompanyName (String companyType, String companyId) {
        if ( StringUtils.isBlank ( companyType ) || StringUtils.isBlank ( companyId ) ) {
            return "";
        }
        String transactionCompany = "";
        switch ( companyType ) {
            case "BD_Customer":
                CustomerEntity customerEntity = iCustomerService.getById ( companyId );
                if ( customerEntity != null )
                    transactionCompany = customerEntity.getCustomerName ();
                break;
            case "BD_Supplier":
                SupplierEntity supplierEntity = iSupplierService.getById ( companyId );
                if ( supplierEntity != null )
                    transactionCompany = supplierEntity.getSupplierName ();
                break;
            case "BD_Department":
                SysDept sysDept = iSysDeptService.getById ( companyId );
                if ( sysDept != null )
                    transactionCompany = sysDept.getDeptName ();
                break;
            case "BD_Empinfo":
                SysUser sysUser = iSysUserService.getById ( companyId );
                if ( sysUser != null )
                    transactionCompany = sysUser.getNickName ();
                break;
            case "FIN_OTHERS":
                KingBaseTransactionsCompanyEntity transactionsCompanyEntity = iKingBaseTransactionsCompanyService.getById ( companyId );
                if ( transactionsCompanyEntity != null )
                    transactionCompany = transactionsCompanyEntity.getTitle ();
                break;
            case "ORG_Organizations":
                SysDept organ = iSysDeptService.getById ( companyId );
                if ( organ != null )
                    transactionCompany = organ.getDeptName ();
                break;
            case "BD_BANK":
                KingBaseBankEntity bankEntity = iKingBaseBankService.getById ( companyId );
                if ( bankEntity != null )
                    transactionCompany = bankEntity.getTitle ();
                break;
        }
        return transactionCompany;
    }

}
